#ifndef Mathematics_h__
#define Mathematics_h__

// floating point and integer sign bit tests
#define FLOATSIGNBITSET(f)		((*(const unsigned int *)&(f)) >> 31)
#define FLOATSIGNBITNOTSET(f)	((~(*(const unsigned int *)&(f))) >> 31)
#define FLOATNOTZERO(f)			((*(const unsigned int *)&(f)) & ~(1<<31))
#define INTSIGNBITSET(i)		(((const unsigned int)(i)) >> 31)
#define INTSIGNBITNOTSET(i)		((~((const unsigned int)(i))) >> 31)
#define SHORTSIGNBITSET(i)		(((const unsigned int)(i)) >> 15)
#define SHORTSIGNBITNOTSET(i)	((~((const unsigned int)(i))) >> 15)

// floating point special value tests
#define	FLOAT_IS_NAN(x)			(((*(const unsigned int *)&(x)) & 0x7f800000) == 0x7f800000)
#define FLOAT_IS_INF(x)			(((*(const unsigned int *)&(x)) & 0x7fffffff) == 0x7f800000)
#define FLOAT_IS_IND(x)			((*(const unsigned int *)&(x)) == 0xffc00000)
#define	FLOAT_IS_DENORMAL(x)	(((*(const unsigned int *)&(x)) & 0x7f800000) == 0x00000000 && \
                                    ((*(const unsigned int *)&(x)) & 0x007fffff) != 0x00000000 )

#include <cmath>

#undef max
#undef min
#undef sign
#undef fabs

namespace inf {

    namespace math {
        // limits
        static const signed char       LIMITS_CHAR_MIX = (-128);
        static const signed char       LIMITS_CHAR_MAX = 127;
        static const unsigned char     LIMITS_UNSIGNED_CHAR_MAX = 0xff;

        static const signed short       LIMITS_SHORT_MIX = (-32768);
        static const signed short       LIMITS_SHORT_MAX = 32767;
        static const unsigned short     LIMITS_UNSIGNED_SHORT_MAX = 0xffff;

        static const signed int         LIMITS_INTEGER_MIN = (-2147483647 - 1);
        static const signed int         LIMITS_INTEGER_MAX = 2147483647;
        static const unsigned int       LIMITS_UNSIGNED_INTEGER_MAX = 0xffffffff;

#if (INF_COMPILER != PLATFORM_IOS)

		static const int64              LIMITS_INTEGER64_MIN = (-9223372036854775807i64 - 1);
		static const int64              LIMITS_INTEGER64_MAX = 9223372036854775807i64;
        
        static const uint64             LIMITS_UNSIGNED_INTEGER64_MAX = 0xffffffffffffffffui64;
#endif
   


        extern const float      LIMITS_FLOAT_MAX;
        extern const float      LIMITS_FLOAT_MIN;
        extern const double     LIMITS_DOUBLE_MAX;
        extern const double     LIMITS_DOUBLE_MIN;

        // floating point bit layouts according to the IEEE standard
        extern const int IEEE_FLT_MANTISSA_BITS;
        extern const int IEEE_FLT_EXPONENT_BITS;
        extern const int IEEE_FLT_EXPONENT_BIAS;
        extern const int IEEE_FLT_SIGN_BIT;

        extern const int IEEE_DBL_MANTISSA_BITS;
        extern const int IEEE_DBL_EXPONENT_BITS;
        extern const int IEEE_DBL_EXPONENT_BIAS;
        extern const int IEEE_DBL_SIGN_BIT;

        extern const int IEEE_DBLE_MANTISSA_BITS;
        extern const int IEEE_DBLE_EXPONENT_BITS;
        extern const int IEEE_DBLE_EXPONENT_BIAS;
        extern const int IEEE_DBLE_SIGN_BIT;

        extern const float			PI;							// pi
        extern const float			TWO_PI;						// pi * 2
        extern const float			HALF_PI;					// pi / 2
        extern const float			ONEFOURTH_PI;				// pi / 4
        extern const float			THREEFOURTHS_PI;			// 3 * pi / 4
        extern const float			E;							// e
        extern const float			SQRT_TWO;					// sqrt( 2 )
        extern const float			SQRT_THREE;					// sqrt( 3 )
        extern const float			SQRT_1OVER2;				// sqrt( 1 / 2 )
        extern const float			SQRT_1OVER3;				// sqrt( 1 / 3 )
        extern const float			M_DEG2RAD;					// degrees to radians multiplier
        extern const float			M_RAD2DEG;					// radians to degrees multiplier
        extern const float			M_SEC2MS;					// seconds to milliseconds multiplier
        extern const float			M_MS2SEC;					// milliseconds to seconds multiplier
        extern const float			INFINITY;					// huge number which should be larger than any valid number used
        extern const float			FLOAT_EPSILON;				// smallest positive number such that 1.0+FLOAT_EPSILON != 1.0
#ifdef INF_WIN_X86_SSE
        extern const float			SSE_FLOAT_ZERO;
        extern const float			SSE_FLOAT_255;
#endif
        
        
        
        INF_INLINE int ftoiFast( float f ) {
#if defined(INF_WIN_X86_ASM)
            int i;
            __asm fld		f
            __asm fistp		i		// use default rouding mode (round nearest)
            return i;
#elif 0						// round chop (C/C++ standard)
            int i, s, e, m, shift;
            i = *reinterpret_cast<int *>(&f);
            s = i >> IEEE_FLT_SIGN_BIT;
            e = ( ( i >> IEEE_FLT_MANTISSA_BITS ) & ( ( 1 << IEEE_FLT_EXPONENT_BITS ) - 1 ) ) - IEEE_FLT_EXPONENT_BIAS;
            m = ( i & ( ( 1 << IEEE_FLT_MANTISSA_BITS ) - 1 ) ) | ( 1 << IEEE_FLT_MANTISSA_BITS );
            shift = e - IEEE_FLT_MANTISSA_BITS;
            return ( ( ( ( m >> -shift ) | ( m << shift ) ) & ~( e >> 31 ) ) ^ s ) - s;
            //#elif defined( __i386__ )
#elif 0
            int i = 0;
            __asm__ __volatile__ (
                                  "fld %1\n" \
                                  "fistp %0\n" \
                                  : "=m" (i) \
                                  : "m" (f) );
            return i;
#else
            return static_cast<int>( f );
#endif
        }

        template<class T> T	max( T x, T y ) { return ( x > y ) ? x : y; }
        template<class T> T	min( T x, T y ) { return ( x < y ) ? x : y; }
        template<class T> int	max_index( T x, T y ) { return  ( x > y ) ? 0 : 1; }
        template<class T> int	min_index( T x, T y ) { return ( x < y ) ? 0 : 1; }

        template<class T> T	max3( T x, T y, T z ) { return ( x > y ) ? ( ( x > z ) ? x : z ) : ( ( y > z ) ? y : z ); }
        template<class T> T	min3( T x, T y, T z ) { return ( x < y ) ? ( ( x < z ) ? x : z ) : ( ( y < z ) ? y : z ); }
        template<class T> int	max3_index( T x, T y, T z ) { return ( x > y ) ? ( ( x > z ) ? 0 : 2 ) : ( ( y > z ) ? 1 : 2 ); }
        template<class T> int	min3_index( T x, T y, T z ) { return ( x < y ) ? ( ( x < z ) ? 0 : 2 ) : ( ( y < z ) ? 1 : 2 ); }

        template<class T> T	sign( T f ) { return ( f > 0 ) ? 1 : ( ( f < 0 ) ? -1 : 0 ); }
        template<class T> T	square( T x ) { return x * x; }
        template<class T> T	cube( T x ) { return x * x * x; }


        // run-time conversion from seconds to milliseconds and vice versa
        template< typename T > int MINS2MS( const T value ) { return ftoiFast( value * M_SEC2MS * 60.f ); }
        template< typename T > int SEC2MS( const T value ) { return math::ftoiFast( value * math::M_SEC2MS ); }
        template< typename T > float MS2SEC( const T value ) { return static_cast< float >( value * math::M_MS2SEC ); }







        void				init( void );

        float				rsqrt( float x );			// reciprocal square root, returns huge number when x == 0.0

        float				inv_sqrt( float x );			// inverse square root with 32 bits precision, returns huge number when x == 0.0
        float				inv_sqrt16( float x );		// inverse square root with 16 bits precision, returns huge number when x == 0.0
        double				int_sqrt64( float x );		// inverse square root with 64 bits precision, returns huge number when x == 0.0

        float				sqrt( float x );			// square root with 32 bits precision
        float				sqrt16( float x );			// square root with 16 bits precision
        double				sqrt64( float x );			// square root with 64 bits precision

        float				sin( float a );				// sine with 32 bits precision
        float				sin16( float a );			// sine with 16 bits precision, maximum absolute error is 2.3082e-09
        double				sin64( float a );			// sine with 64 bits precision

        float				cos( float a );				// cosine with 32 bits precision
        float				cos16( float a );			// cosine with 16 bits precision, maximum absolute error is 2.3082e-09
        double				cos64( float a );			// cosine with 64 bits precision

        void					sincos( float a, float &s, float &c );		// sine and cosine with 32 bits precision
        void					sincos16( float a, float &s, float &c );	// sine and cosine with 16 bits precision
        void					sincos64( float a, double &s, double &c );	// sine and cosine with 64 bits precision

        float				tan( float a );				// tangent with 32 bits precision
        float				tan16( float a );			// tangent with 16 bits precision, maximum absolute error is 1.8897e-08
        double				tan64( float a );			// tangent with 64 bits precision

        float				asin( float a );			// arc sine with 32 bits precision, input is clamped to [-1, 1] to avoid a silent NaN
        float				asin16( float a );			// arc sine with 16 bits precision, maximum absolute error is 6.7626e-05
        double				asin64( float a );			// arc sine with 64 bits precision

        float				acos( float a );			// arc cosine with 32 bits precision, input is clamped to [-1, 1] to avoid a silent NaN
        float				acos16( float a );			// arc cosine with 16 bits precision, maximum absolute error is 6.7626e-05
        double				acos64( float a );			// arc cosine with 64 bits precision

        float				atan( float a );			// arc tangent with 32 bits precision
        float				atan16( float a );			// arc tangent with 16 bits precision, maximum absolute error is 1.3593e-08
        double				atan64( float a );			// arc tangent with 64 bits precision

        float				atan( float y, float x );	// arc tangent with 32 bits precision
        float				atan16( float y, float x );	// arc tangent with 16 bits precision, maximum absolute error is 1.3593e-08
        double				atan64( float y, float x );	// arc tangent with 64 bits precision

        float				pow( float x, float y );	// x raised to the power y with 32 bits precision
        float				pow16( float x, float y );	// x raised to the power y with 16 bits precision
        double				pow64( float x, float y );	// x raised to the power y with 64 bits precision

        float				exp( float f );				// e raised to the power f with 32 bits precision
        float				exp16( float f );			// e raised to the power f with 16 bits precision
        double				exp64( float f );			// e raised to the power f with 64 bits precision

        float				log( float f );				// natural logarithm with 32 bits precision
        float				log16( float f );			// natural logarithm with 16 bits precision
        double				log64( float f );			// natural logarithm with 64 bits precision

        int					ipow( int x, int y );		// integral x raised to the power y
        int					ilog2( float f );			// integral base-2 logarithm of the floating point value
        int					ilog2( int i );				// integral base-2 logarithm of the integer value

        int					bits_for_float( float f );	// minimum number of bits required to represent ceil( f )
        int					bits_for_float( float max, float min );	// minimum number of bits required to represent everything between min & max (min being the minimum relevant precision)
        int					bits_for_integer( int i );	// minimum number of bits required to represent i
        int					mask_for_float_sign( float f );// returns 0x00000000 if x >= 0.0f and returns 0xFFFFFFFF if x <= -0.0f
        int					mask_for_integer_sign( int i );// returns 0x00000000 if x >= 0 and returns 0xFFFFFFFF if x < 0
        int					floor_power_of_two( int x );	// round x down to the first power of 2, returns x if x is a power of two
        int					ceil_power_of_two( int x );	// round x up to the first power of 2, returns x if x is a power of two
        int					lower_power_of_two( int x );	// round x down to the first power of 2
        int					higher_power_of_two( int x );	// round x up to the first power of 2
        bool				is_power_of_two( int x );		// returns true if x is a power of 2
        int					bit_count( int x );			// returns the number of 1 bits in x
        int					bit_reverse( int x );		// returns the bit reverse of x

        int					abs( int x );				  // returns the absolute value of the integer value (for reference only)
        float				fabs( float f );			// returns the absolute value of the floating point value
        float				floor( float f );			// returns the largest integer that is less than or equal to the given value
        float				ceil( float f );			// returns the smallest integer that is greater than or equal to the given value
        float				rint( float f );			// returns the nearest integer
        int					ftoi( float f );			// float to int conversion
        int					ftoiFast( float f );		// fast float to int conversion but uses current FPU round mode (default round nearest)
        unsigned long		ftol( float f );			// float to long conversion
        unsigned long		ftolFast( float );			// fast float to long conversion but uses current FPU round mode (default round nearest)
        byte				ftob( float f );			// float to byte conversion, the result is clamped to the range [0-255]

        signed char			clamp_char( int i );
        signed short		clamp_short( int i );
        int					clamp_int( int minValue, int maxValue, int value );
        float				clamp_float( float minValue, float maxValue, float value );

        float				angle_normalize_360( float angle );
        float				angle_normalize_180( float angle );
        float				angle_delta( float angle1, float angle2 );

        // BEGIN non-inline
        int					float_to_bits( float f, int exponentBits, int mantissaBits );
        float				bits_to_float( int i, int exponentBits, int mantissaBits );
        void				test_float_bit_conversions();	// unit test for float_to_bits & bits_to_float
        // END non-inline

        int					float_hash( const float *array, const int numFloats );

        float				sign( float f );
        float				fmod( float x, float y );
        float				modf( float f, float& i );
        float				modf( float f );

        bool				float_is_zero( const float f );

        float				DEG2RAD(float a);
        float				RAD2DEG(float a);


        namespace Private {
            enum {
                LOOKUP_BITS				= 8,
                EXP_POS					= 23,
                EXP_BIAS				= 127,
                LOOKUP_POS				= (EXP_POS-LOOKUP_BITS),
                SEED_POS				= (EXP_POS-8),
                SQRT_TABLE_SIZE			= (2<<LOOKUP_BITS),
                LOOKUP_MASK				= (SQRT_TABLE_SIZE-1)
            };

            union _flint {
                dword					i;
                float					f;
            };

            extern dword				iSqrt[SQRT_TABLE_SIZE];
            extern bool					initialized;
        }

    }   // ::math

    INF_INLINE float math::rsqrt( float x ) {
        // NOTE: allows x == 0
        long i;
        float y, r;

        y = x * 0.5f;
        i = *reinterpret_cast<long *>( &x );
        i = 0x5f3759df - ( i >> 1 );
        r = *reinterpret_cast<float *>( &i );
        r = r * ( 1.5f - r * r * y );
        return r;
    }

    INF_INLINE float math::inv_sqrt16( float x ) {
        assert( x != 0.f );
        dword a = ((union Private::_flint*)(&x))->i;
        union Private::_flint seed;

        assert( Private::initialized );

        double y = x * 0.5f;
        seed.i = (( ( (3*Private::EXP_BIAS-1) - ( (a >> Private::EXP_POS) & 0xFF) ) >> 1)<<Private::EXP_POS) | Private::iSqrt[(a >> (Private::EXP_POS-Private::LOOKUP_BITS)) & Private::LOOKUP_MASK];
        double r = seed.f;
        r = r * ( 1.5f - r * r * y );
        return (float) r;
    }

    INF_INLINE float math::sqrt16( float x ) {
        return x * inv_sqrt16( x );
    }

    INF_INLINE void math::sincos( float a, float &s, float &c ) {
#if defined(INF_WIN_X86_ASM)
        _asm {
            fld		a
                fsincos
                mov		ecx, c
                mov		edx, s
                fstp	dword ptr [ecx]
            fstp	dword ptr [edx]
        }
#elif (INF_COMPILER == PLATFORM_IOS)
        s = sinf( a );
        c = cosf( a ); 
 #else
        s =  sinf( a );
        c =  cosf( a );
#endif
    }

    INF_INLINE void math::sincos64( float a, double &s, double &c ) {
#if defined(INF_WIN_X86_ASM)
        _asm {
            fld		a
                fsincos
                mov		ecx, c
                mov		edx, s
                fstp	qword ptr [ecx]
            fstp	qword ptr [edx]
        }
#else
        s = sin( a );
        c = cos( a );
#endif
    }

    INF_INLINE float math::pow16( float x, float y ) {
        return exp16( y * log16( x ) );
    }

    INF_INLINE float math::exp16( float f ) {
        int i, s, e, m, exponent;
        float x, x2, y, p, q;

        x = f * 1.44269504088896340f;		// multiply with ( 1 / log( 2 ) )
#if 1
        i = *reinterpret_cast<int *>(&x);
        s = ( i >> IEEE_FLT_SIGN_BIT );
        e = ( ( i >> IEEE_FLT_MANTISSA_BITS ) & ( ( 1 << IEEE_FLT_EXPONENT_BITS ) - 1 ) ) - IEEE_FLT_EXPONENT_BIAS;
        m = ( i & ( ( 1 << IEEE_FLT_MANTISSA_BITS ) - 1 ) ) | ( 1 << IEEE_FLT_MANTISSA_BITS );
        i = ( ( m >> ( IEEE_FLT_MANTISSA_BITS - e ) ) & ~( e >> 31 ) ) ^ s;
#else
        i = (int) x;
        if ( x < 0.0f ) {
            i--;
        }
#endif
        exponent = ( i + IEEE_FLT_EXPONENT_BIAS ) << IEEE_FLT_MANTISSA_BITS;
        y = *reinterpret_cast<float *>(&exponent);
        x -= (float) i;
        if ( x >= 0.5f ) {
            x -= 0.5f;
            y *= 1.4142135623730950488f;	// multiply with sqrt( 2 )
        }
        x2 = x * x;
        p = x * ( 7.2152891511493f + x2 * 0.0576900723731f );
        q = 20.8189237930062f + x2;
        x = y * ( q + p ) / ( q - p );
        return x;
    }

    INF_INLINE float math::log16( float f ) {
        int i, exponent;
        float y, y2;

        i = *reinterpret_cast<int *>(&f);
        exponent = ( ( i >> IEEE_FLT_MANTISSA_BITS ) & ( ( 1 << IEEE_FLT_EXPONENT_BITS ) - 1 ) ) - IEEE_FLT_EXPONENT_BIAS;
        i -= ( exponent + 1 ) << IEEE_FLT_MANTISSA_BITS;	// get value in the range [.5, 1>
        y = *reinterpret_cast<float *>(&i);
        y *= 1.4142135623730950488f;						// multiply with sqrt( 2 )
        y = ( y - 1.0f ) / ( y + 1.0f );
        y2 = y * y;
        y = y * ( 2.000000000046727f + y2 * ( 0.666666635059382f + y2 * ( 0.4000059794795f + y2 * ( 0.28525381498f + y2 * 0.2376245609f ) ) ) );
        y += 0.693147180559945f * ( (float)exponent + 0.5f );
        return y;
    }

    INF_INLINE int math::ipow( int x, int y ) {
        int r; for( r = x; y > 1; y-- ) { r *= x; } return r;
    }

    INF_INLINE int math::ilog2( float f ) {
        return ( ( (*reinterpret_cast<int *>(&f)) >> IEEE_FLT_MANTISSA_BITS ) & ( ( 1 << IEEE_FLT_EXPONENT_BITS ) - 1 ) ) - IEEE_FLT_EXPONENT_BIAS;
    }

    INF_INLINE int math::ilog2( int i ) {
        return ilog2( (float)i );
    }

    INF_INLINE int math::bits_for_integer( int i ) {
        return ilog2( (float)i ) + 1;
    }

    INF_INLINE int math::mask_for_float_sign( float f ) {
        return ( (*reinterpret_cast<int *>(&f)) >> 31 );
    }

    INF_INLINE int math::mask_for_integer_sign( int i ) {
        return ( i >> 31 );
    }

    INF_INLINE int math::floor_power_of_two( int x ) {
        return math::is_power_of_two( x ) ? x : higher_power_of_two( x ) >> 1;
    }

    INF_INLINE int math::ceil_power_of_two( int x ) {
        if ( math::is_power_of_two( x ) ) {
            return x;
        }

        x--;
        x |= x >> 1;
        x |= x >> 2;
        x |= x >> 4;
        x |= x >> 8;
        x |= x >> 16;
        x++;
        return x;
    }

    INF_INLINE int math::lower_power_of_two( int x ) {
        return higher_power_of_two( x ) >> 1;
    }

    INF_INLINE int math::higher_power_of_two( int x ) {
        x--;
        x |= x >> 1;
        x |= x >> 2;
        x |= x >> 4;
        x |= x >> 8;
        x |= x >> 16;
        x++;
        return x;
    }

    INF_INLINE bool math::is_power_of_two( int x ) {
        return ( x & ( x - 1 ) ) == 0 && x > 0;
    }

    INF_INLINE int math::bit_count( int x ) {
        x -= ( ( x >> 1 ) & 0x55555555 );
        x = ( ( ( x >> 2 ) & 0x33333333 ) + ( x & 0x33333333 ) );
        x = ( ( ( x >> 4 ) + x ) & 0x0f0f0f0f );
        x += ( x >> 8 );
        return ( ( x + ( x >> 16 ) ) & 0x0000003f );
    }

    INF_INLINE int math::bit_reverse( int x ) {
        x = ( ( ( x >> 1 ) & 0x55555555 ) | ( ( x & 0x55555555 ) << 1 ) );
        x = ( ( ( x >> 2 ) & 0x33333333 ) | ( ( x & 0x33333333 ) << 2 ) );
        x = ( ( ( x >> 4 ) & 0x0f0f0f0f ) | ( ( x & 0x0f0f0f0f ) << 4 ) );
        x = ( ( ( x >> 8 ) & 0x00ff00ff ) | ( ( x & 0x00ff00ff ) << 8 ) );
        return ( ( x >> 16 ) | ( x << 16 ) );
    }

    INF_INLINE int math::abs( int x ) {
        int y = x >> 31;
        return ( ( x ^ y ) - y );
    }

    INF_INLINE int math::ftoi( float f ) {
#if defined(INF_WIN_X86_SSE)
        // If a converted result is larger than the maximum signed doubleword integer,
        // the floating-point invalid exception is raised, and if this exception is masked,
        // the indefinite integer value (80000000H) is returned.
        int i;
        __asm cvttss2si	eax, f
            __asm mov		i, eax
            return i;
#elif defined(INF_WIN_X64_SSE)
        // If a converted result is larger than the maximum signed doubleword integer the result is undefined.
        return static_cast<int>( f );
#endif
    }

  

    INF_INLINE unsigned long math::ftol( float f ) {
        return (unsigned long) f;
    }

    INF_INLINE unsigned long math::ftolFast( float f ) {
#if defined(INF_WIN_X86_ASM)
        unsigned long i;
        __asm fld		f
            __asm fistp		i		// use default rouding mode (round nearest)
            return i;
#elif 0						// round chop (C/C++ standard)
        int i, s, e, m, shift;
        i = *reinterpret_cast<int *>(&f);
        s = i >> IEEE_FLT_SIGN_BIT;
        e = ( ( i >> IEEE_FLT_MANTISSA_BITS ) & ( ( 1 << IEEE_FLT_EXPONENT_BITS ) - 1 ) ) - IEEE_FLT_EXPONENT_BIAS;
        m = ( i & ( ( 1 << IEEE_FLT_MANTISSA_BITS ) - 1 ) ) | ( 1 << IEEE_FLT_MANTISSA_BITS );
        shift = e - IEEE_FLT_MANTISSA_BITS;
        return ( ( ( ( m >> -shift ) | ( m << shift ) ) & ~( e >> 31 ) ) ^ s ) - s;
        //#elif defined( __i386__ )
#elif 0
        // for some reason, on gcc I need to make sure i == 0 before performing a fistp
        int i = 0;
        __asm__ __volatile__ (
            "fld %1\n" \
            "fistp %0\n" \
            : "=m" (i) \
            : "m" (f) );
        return i;
#else
        return (unsigned long) f;
#endif
    }

    INF_INLINE byte math::ftob( float f ) {
#if defined(INF_WIN_X86_SSE)
        // If a converted result is negative the value (0) is returned and if the
        // converted result is larger than the maximum byte the value (255) is returned.
        byte b;
        __asm movss		xmm0, f
            __asm maxss		xmm0, SSE_FLOAT_ZERO
            __asm minss		xmm0, SSE_FLOAT_255
            __asm cvttss2si	eax, xmm0
            __asm mov		b, al
            return b;
#elif defined(INF_WIN_X64_SSE)
        // If a converted result is clamped to the range [0-255].
        int i = static_cast<int>( f );
        if ( i < 0 ) {
            return 0;
        } else if ( i > 255 ) {
            return 255;
        }
        return i;
#endif
    }

    INF_INLINE signed char math::clamp_char( int i ) {
        if ( i < -128 ) {
            return -128;
        }
        if ( i > 127 ) {
            return 127;
        }
        return i;
    }

    INF_INLINE signed short math::clamp_short( int i ) {
        if ( i < -32768 ) {
            return -32768;
        }
        if ( i > 32767 ) {
            return 32767;
        }
        return i;
    }

    INF_INLINE int math::clamp_int( int minValue, int maxValue, int value ) {
        if ( value < minValue ) {
            return minValue;
        }
        if ( value > maxValue ) {
            return maxValue;
        }
        return value;
    }

    INF_INLINE float math::clamp_float( float minValue, float maxValue, float value ) {
        if ( value < minValue ) {
            return minValue;
        }
        if ( value > maxValue ) {
            return maxValue;
        }
        return value;
    }

    INF_INLINE float math::angle_normalize_180( float angle ) {
        angle = angle_normalize_360( angle );
        if ( angle > 180.0f ) {
            angle -= 360.0f;
        }
        return angle;
    }

    INF_INLINE float math::angle_delta( float angle1, float angle2 ) {
        return angle_normalize_180( angle1 - angle2 );
    }

    INF_INLINE int math::float_hash( const float *array, const int numFloats ) {
        int i, hash = 0;
        const int *ptr;

        ptr = reinterpret_cast<const int *>( array );
        for ( i = 0; i < numFloats; i++ ) {
            hash ^= ptr[i];
        }
        return hash;
    }

    INF_INLINE float math::sign( float f )	{
        if ( f > 0.0f ) {
            return 1.0f;
        }
        if ( f < 0.0f ) {
            return -1.0f;
        }
        return 0.0f;
    }

    INF_INLINE bool math::float_is_zero( const float f ) {
        return ( math::fabs( f ) < math::FLOAT_EPSILON );
    }

    INF_INLINE float math::DEG2RAD(float a) {
        return (a) * math::M_DEG2RAD;
    }

    INF_INLINE float math::RAD2DEG(float a)	{
        return (a) * math::M_RAD2DEG;
    }

}   // ::inf

#if defined( _DEBUG )
//#define ENABLE_FLOAT_CHECKS
#endif

#ifdef ENABLE_FLOAT_CHECKS
#	define FLOAT_CHECK_BAD( x ) { \
    if ( FLOAT_IS_NAN( x ) || FLOAT_IS_INF( x ) || FLOAT_IS_IND( x ) || FLOAT_IS_DENORMAL( x ) ) { \
    __debugbreak(); \	// not add???
    } \
}
#	define VEC_CHECK_BAD( vec ) { \
    FLOAT_CHECK_BAD( ( vec ).x ) \
    FLOAT_CHECK_BAD( ( vec ).y ) \
    FLOAT_CHECK_BAD( ( vec ).z ) \
    }
#else
#	define FLOAT_CHECK_BAD( x )  ;
#	define VEC_CHECK_BAD( vec )   ;
#endif

#endif // Mathematics_h__
